JavaScript數字分類比較簡約,不像一般的程式語言不同,數字能再細分成
Floating(浮點數型)、Integers(整數型)、double(雙精度型)或是Bignum(大數型)
,
JavaScript只有兩種,分別是number跟bigint,接下來讓鯊魚來一一介紹。
number是使用雙精度浮點數(double)儲存的數值,他的精確度可以到正負2的53次方-1(2**53-1)
在這之上精確度會失準,用常見的等式來說明
// 2**53-1以內時
2**53-1 === 2**53-2
// 可以精確的回報false
// 可是當你超過2**53-1時
2**53 === 2**53+1
// 此時卻回報了true
2**53+2 === 2**53+3
// 而此時卻回報了false
會有這樣的結果是因為他超出雙精度浮點數的精確度範圍了,
也就是超出2的53次方以上了,沒辦法判斷如此的精確
而且超出越多精確度越差,另外number一次只能處理16位數
超出的部分會從後面以0代替,而進位與否要看浮點數的精確度比較偏向哪一邊
360287970189639765
// 輸入上的超過16位數的數字
360287970189639740
// 回傳的數字比輸出少了15
由上面的例子可以看出16位之後65,因為浮點數的精確度問題而跟輸出的值有所出入
所以當你有必須使用到超過2的53次方的數字請使用下面介紹的bigint型別。
先前我們提到number是使用雙精度浮點數(double)儲存的數值
值往上超過2的53次方會失去精準,而因為儲存方式的關係
十進位制的小數無法用二進位完美的呈現
所以小數的運算會出現一些無法預期的錯誤
0.2 + 0.4 ===0.6
// false
因為儲存方式的關係,小數會有一些的精度誤差,如果要做小數的運算
建議先轉成整數在做運算,雖然會碰到大雖然有機會碰到bigint超出範圍的狀況
除了十進位之外,JavaScript還支援16及2進位,
0xaf
// 175 16進位
0b11
// 3 2進位
8進位在ECMAScript標準未支援,但是某些可以實作,有些不行,
所以不建議使用,因為無法確定,這是會被當作10進位還是8進位使用
而導致出現無法預期的結果
此外,因為number是使用雙精度浮點數(double)儲存的數值,
所以他的最大上/下限便是正/負2的1024次方,但bigint可以超出這範圍
2**1024
// Infinity
-(2**1024)
// -Infinity
從字面上來看,他不是個數字,但是用typeof NaN鑑定
他又會回傳是一個數字,那他到底是是什麼呢?
鯊魚個人的解釋是這樣的:
在應該回傳的數字的結果中,出現了不是數字的結果這時就會回傳NaN
就像是
Number("String")
// NaN
Number()理應回傳一個數字,但是"String"無法轉變成數字
所以只好回傳一個數字型別的NaN來表示"String"無法被變成數字
NaN是一個相當獨特的存在,他不是任何人包含他自己
所以 NaN 不等於 NaN
NaN !== NaN
// true
因此產生了一個專門判斷NaN的東西 isNaN(),在寫判斷式的時候很好用
isNaN(NaN)
// true
另外任何數字遇上NaN都會被NaN併吞,最後只會剩下NaN
就像鯊魚會吞噬獵物,最後只會剩下鯊魚
20+NaN
// NaN
bigint字面上來說就是大整數(big Integers)專門處理超過2的53次方的數字
轉成這種型別很簡單
像下面這樣
9527n
// 9527n
BigInt(9527)
// 9527n
面對大數字的時候跟number的差別
3602879701896397652
// 3602879701896398000
3602879701896397652n
// 3602879701896397652n
// 之前number無法完整呈現的數字,用bigint就能完整呈現了
但是bigint雖然可以處理大數字的運算,但是他的不能跟其他類型混用,除了字串
20n + 2
// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions at <anonymous>:1:5
// BigInt不能跟其他類型混用
20n + "20"
// 2020
// 不過卻能跟字串結合,而且是轉成數字之後再跟字串結合
如果要bigint 跟 number 做運算則必須轉成同一類型
不過如果要將bigint轉成number有可能會喪失部分的精度
所以比較推薦都轉成bigint去做運算
另外bigint顧名思義就是大數字,所以他不負責處理小數的部分
有小數的值無法轉成bigint,而bigint運算出有小數的結果都會無條件捨去小數的值
7n/4n
// 1n 小數點後面直接捨去
bigint是少數在四則運算中不會自動轉型的一個型別
但是如果拿 bigint 跟 number 做比較
會發現他們是可以被比較的
1n < 2
// true
1n == 1
// true
1n === 1
// false
// 因為透過轉型,他們是不完全相等但是不是完全相等
boolean他代表著truth(真實)或是falsehood(虛假),
常用來表示判斷/比較的結果,而他的值只有兩個true(真實)跟false(錯誤),
也是if/else述句常出現的判斷基準或是for迴圈的執行與終止的條件。
特別注意:
數字的0跟空字串""會自動轉型成boolean的false
數字的1會自動轉型成boolean的true
這些小細節可以好好的運用在if/else述句上面
可以剩下很多判斷的功夫
曾經Chris說過,如果想要學得快就自己學
如果想學的久,就大家陪你一起學
你們願意陪鯊魚一起學習一起成長嗎?
基礎是一個重要但是很無趣的東西
而且一隻鯊魚能看到的東西相當有限
如果有遺漏的地方,還請大家多多指點我
讓我們一起走得更遠。
參考資料